#pragma once

#include "basic_config.hpp"

namespace zuck
{
    // quotient & remainder
    template<typename Integer>
    class divide {
    private:
        Integer _M_q;
        Integer _M_r;
    public:
        constexpr explicit divide(const Integer& q, const Integer& r)
            : _M_q(q), _M_r(r) {}

        constexpr explicit divide(Integer&& q, Integer&& r)
            : _M_q(q), _M_r(r) {}

        constexpr divide(const divide& other)
            : _M_q(other._M_q), _M_r(other._M_r) {}

        constexpr divide(divide&& other)noexcept
            : _M_q(other._M_q), _M_r(other._M_r)
        {
            other._M_q = 0;
            other._M_r = 0;
        }

        [[nodiscard]] constexpr Integer& q()const noexcept { return _M_q; }

        [[nodiscard]] constexpr Integer& r()const noexcept { return _M_r; }

        constexpr divide& operator=(const divide& other)
        {
            _M_q = other._M_q;
            _M_r = other._M_r;
            return *this;
        }

        constexpr divide& operator=(divide&& other)noexcept
        {
            _M_q = other._M_q;
            _M_r = other._M_r;
            other._M_q = Integer{};
            other._M_r = Integer{};
            return *this;
        }

    public:
        template<typename Ostream, typename T>
        friend Ostream& operator<<(Ostream& os, const divide<T>& div)
        {
            os << '(' << div.q() << ", " << div.r() << ")\n";
            return os;
        }
    };
}

